package cn.hwadee.muying.recommend;

import cn.hwadee.muying.recommend.util.ExcelUtil;
import cn.hwadee.muying.recommend.util.FileUtil;
import cn.hwadee.muying.recommend.util.ScoreCos;
import cn.hwadee.muying.recommend.util.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @创建人 skiner
 * @创建时间 2018/8/13
 * @描述
 */
public class ContentSimilar {

    private static Logger log = LoggerFactory.getLogger(ContentSimilar.class);

    public static void main(String[] args) throws IOException {
        useStreamApi();
    }

    private static void useNormal() throws IOException {
        //数据结构

        //结果
        Map<Long,List<Node>> map = new HashMap<>();

        //结果的每一行
        Map<Long, Double> row = new HashMap<>();

        //文件内容
        Map<Long, String> content = new HashMap<>();

        //读取文件
        File file = new File("d:/data7.xls");
        InputStream inputStream = new FileInputStream(file);
        Workbook workbook = ExcelUtil.getWorkbok(inputStream,file);
        Sheet sheet = workbook.getSheetAt(0);

        //跳过第一个
        for (int i = 1; i < sheet.getLastRowNum(); i++) {
            Row r = sheet.getRow(i);
            Cell id = r.getCell(9);
            Cell cont = r.getCell(5);
            content.put(Long.valueOf(id.getStringCellValue()), cont.getStringCellValue());
        }
//        System.out.println(content);

        //两个for循环计算相似度，取前10个
        for (Map.Entry<Long,String> c1:content.entrySet()) {
            Map<Long, Double> m = new HashMap<>();
            for (Map.Entry<Long,String> c2:content.entrySet()) {
                if(c1.getKey().equals(c2.getKey())) continue;
                double r = ScoreCos.similarScoreCos(c1.getValue(), c2.getValue());
                m.put(c2.getKey(), r);
            }
            List<Map.Entry<Long,Double>> list = new ArrayList<Map.Entry<Long,Double>>(m.entrySet());
            Collections.sort(list,new MyComparator());
            List<Node> nodeList = new ArrayList<>();
            for(int i = 0; i< 10 && i < list.size(); i++){
                Map.Entry<Long, Double> entry = list.get(i);
                nodeList.add(new Node(entry.getKey(), entry.getValue()));
            }
            map.put(c1.getKey(), nodeList);
            log.info("key:{},value:{}",c1.getKey(),nodeList);
        }


        //保存为文件
        save(map);
    }

    /**
     * 流处理
     * @throws IOException
     */
    private static void useStreamApi() throws IOException {
        List<Worker> data = getFromDB();

        Map<Long, List<Node>> map = new ConcurrentHashMap<>();
        AtomicInteger integer = new AtomicInteger();
        //并发执行
        data.parallelStream().forEach(x->{
            //相当于两个for循环
            List<Node> nodes = data.stream()
                //如果userId相同，则置为0
                .map(y -> new Node(y.getUserId(), x.getUserId()==y.getUserId()?0:x.distinct(y)))
                //降序
                .sorted(Comparator.reverseOrder())
                //取前10个
                .limit(10)
                //.peek(System.out::println)
                .collect(Collectors.toList());
            map.put(x.getUserId(), nodes);
            //每隔100个输出一次
            if(integer.getAndIncrement()%100==0)
                log.info("key:{} value:{}",x.getUserId(),nodes);
        });
        save(map);
    }

//    /**
//     * 保存到数据库
//     * @param list
//     */
//    private static void insertToDB(List<Recommend> list) {
//
//    }

    /**
     * 从数据库获取数据，失败时返回null
     * @return
     */
    private static List<Worker> getFromDB(){
        SqlSession session = SqlSessionFactoryUtils.openSession();
        WorkerMapper workerMapper = session.getMapper(WorkerMapper.class);
        try {
            return workerMapper.list();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    private static void save(Map<Long,List<Node>> map) throws IOException {
        File file = FileUtil.get("d:/", "ret", "xls");
        Workbook workbook = new HSSFWorkbook();
        Sheet sheet = workbook.createSheet();
        List<Map.Entry<Long, List<Node>>> list = new ArrayList<>(map.entrySet());
        for (int i = 0; i < list.size(); i++) {
            Map.Entry<Long, List<Node>> entry = list.get(i);
            Row row = sheet.createRow(i);
            Cell cell = row.createCell(0);
            cell.setCellValue(entry.getKey());
            List<Node> nodeList = entry.getValue();
            for (int j = 1; j <= nodeList.size(); j++) {
                cell = row.createCell(j);
                cell.setCellValue(nodeList.get(j-1).getId());
            }
        }
        workbook.write(new FileOutputStream(file));
    }
}
